package org.apache.james.mime4j.decoder;

import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class QuotedPrintableInputStream extends InputStream
{
  static Class class$org$apache$james$mime4j$decoder$QuotedPrintableInputStream;
  private static Log log;
  ByteQueue byteq = new ByteQueue();
  private boolean closed;
  ByteQueue pushbackq = new ByteQueue();
  private byte state = 0;
  private InputStream stream;

  static
  {
    Class localClass;
    if (class$org$apache$james$mime4j$decoder$QuotedPrintableInputStream == null)
    {
      localClass = class$("org.apache.james.mime4j.decoder.QuotedPrintableInputStream");
      class$org$apache$james$mime4j$decoder$QuotedPrintableInputStream = localClass;
    }
    while (true)
    {
      log = LogFactory.getLog(localClass);
      return;
      localClass = class$org$apache$james$mime4j$decoder$QuotedPrintableInputStream;
    }
  }

  public QuotedPrintableInputStream(InputStream paramInputStream)
  {
    this.closed = false;
    this.stream = paramInputStream;
  }

  private byte asciiCharToNumericValue(byte paramByte)
  {
    int i;
    if ((paramByte >= 48) && (paramByte <= 57))
      i = paramByte - 48;
    while (true)
    {
      while (true)
      {
        return i;
        if ((paramByte < 65) || (paramByte > 90))
          break;
        i = 10 + paramByte - 65;
      }
      if ((paramByte < 97) || (paramByte > 122))
        break;
      i = 10 + paramByte - 97;
    }
    throw new IllegalArgumentException((char)paramByte + " is not a hexadecimal digit");
  }

  static Class class$(String paramString)
  {
    Class localClass;
    try
    {
      localClass = Class.forName(paramString);
      return localClass;
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError().initCause(localClassNotFoundException);
    }
  }

  private void fillBuffer()
    throws IOException
  {
    byte b1 = 0;
    while (true)
    {
      label37: byte b2;
      while (true)
      {
        while (true)
        {
          while (true)
          {
            while (true)
            {
              while (true)
              {
                while (true)
                {
                  while (true)
                  {
                    while (true)
                    {
                      while (true)
                      {
                        while (true)
                        {
                          if (this.byteq.count() == 0)
                          {
                            if (this.pushbackq.count() != 0)
                              break label37;
                            populatePushbackQueue();
                            if (this.pushbackq.count() != 0)
                              break label37;
                          }
                          return;
                          b2 = this.pushbackq.dequeue();
                          switch (this.state)
                          {
                          default:
                            log.error("Illegal state: " + this.state);
                            this.state = 0;
                            this.byteq.enqueue(b2);
                          case 0:
                          case 1:
                          case 2:
                          case 3:
                          }
                        }
                        if (b2 == 61)
                          break;
                        this.byteq.enqueue(b2);
                      }
                      this.state = 1;
                    }
                    if (b2 != 13)
                      break;
                    this.state = 2;
                  }
                  if ((((b2 < 48) || (b2 > 57))) && (((b2 < 65) || (b2 > 70))) && (((b2 < 97) || (b2 > 102))))
                    break;
                  this.state = 3;
                  b1 = b2;
                }
                if (b2 != 61)
                  break;
                if (log.isWarnEnabled())
                  log.warn("Malformed MIME; got ==");
                this.byteq.enqueue(61);
              }
              if (log.isWarnEnabled())
                log.warn("Malformed MIME; expected \\r or [0-9A-Z], got " + b2);
              this.state = 0;
              this.byteq.enqueue(61);
              this.byteq.enqueue(b2);
            }
            if (b2 != 10)
              break;
            this.state = 0;
          }
          if (log.isWarnEnabled())
            log.warn("Malformed MIME; expected 10, got " + b2);
          this.state = 0;
          this.byteq.enqueue(61);
          this.byteq.enqueue(13);
          this.byteq.enqueue(b2);
        }
        if ((((b2 < 48) || (b2 > 57))) && (((b2 < 65) || (b2 > 70))) && (((b2 < 97) || (b2 > 102))))
          break;
        int i = asciiCharToNumericValue(b1);
        int j = asciiCharToNumericValue(b2);
        this.state = 0;
        this.byteq.enqueue(j | i << 4);
      }
      if (log.isWarnEnabled())
        log.warn("Malformed MIME; expected [0-9A-Z], got " + b2);
      this.state = 0;
      this.byteq.enqueue(61);
      this.byteq.enqueue(b1);
      this.byteq.enqueue(b2);
    }
  }

  private void populatePushbackQueue()
    throws IOException
  {
    if (this.pushbackq.count() != 0);
    while (true)
    {
      int i;
      while (true)
      {
        while (true)
        {
          return;
          this.pushbackq.enqueue((byte)i);
          i = this.stream.read();
          switch (i)
          {
          case 9:
          case 32:
          default:
            this.pushbackq.enqueue((byte)i);
          case -1:
          case 10:
          case 13:
          }
        }
        this.pushbackq.clear();
      }
      this.pushbackq.clear();
      this.pushbackq.enqueue((byte)i);
    }
  }

  public void close()
    throws IOException
  {
    this.closed = true;
  }

  public int read()
    throws IOException
  {
    int j;
    if (this.closed)
      throw new IOException("QuotedPrintableInputStream has been closed");
    fillBuffer();
    if (this.byteq.count() == 0)
      j = -1;
    while (true)
    {
      int i;
      while (true)
      {
        return j;
        i = this.byteq.dequeue();
        if (i < 0)
          break;
        j = i;
      }
      j = i & 0xFF;
    }
  }
}